﻿#include "clientthread.h"
#include "../send.h"
#include "../jsonhelp.h"

#include <QTcpSocket>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlResult>
#include <QSqlQueryModel>
#include <QMessageBox>

ClientThread::ClientThread(PutWeighType type, QObject *parent) :
    QThread(parent),/*m_groupid(groupid),m_groupip(groupip),*/m_type(type)
{
    qRegisterMetaType<QVector<int>>("QVector<int>");
    qRegisterMetaType<QMap<QString, QString>>("QMap<QString, QString>");
    //    qRegisterMetaType<GroupItemData>("GroupItemData");
    //    qRegisterMetaType<BatchFeed::ClientConnectType>("BatchFeed::ClientConnectType");
}

ClientThread::ClientThread(QString firstTb, ClientThread::PutWeighType type, QObject *parent)
    :QThread(parent),m_type(type),m_CurrentTb(firstTb)
{
    qRegisterMetaType<QVector<int>>("QVector<int>");
    qRegisterMetaType<QMap<QString, QString>>("QMap<QString, QString>");
}

void ClientThread::run()
{
    QTcpSocket *socket = new QTcpSocket();
//    QByteArray _byte_GetWeighValue;//得到实际值
//    QByteArray byte_weighValue;//得到实际值

    //    QTcpSocket *socket_Put = NULL;

    qDebug()<<"ClientThread:"<<"m_type:"<<m_type<<"tableName:"<<m_data.currentTable()<< m_CurrentTb<<m_groupip<<m_data.IsIgnorError();

    //! [1]称料
    socket->connectToHost(m_groupip,5000);
    if(!socket->waitForConnected()){
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_WeighError,socket->errorString());
        qDebug()<<QStringLiteral("\t网络连接失败，请检查IP地址是否正确.")<<socket->errorString();
        socket->disconnectFromHost();
        socket->deleteLater();
        return;
    }else{
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_WeighConnected,"");
        //get data from sqldatabase.
        QFileInfo fileInfo(m_data.getDBFileName());
        QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE","pir_" + fileInfo.baseName());
        db.setDatabaseName(m_data.getDBFileName());

        if(QFile::exists(m_data.getDBFileName()))
        {
            if(!db.open()){
                qDebug()<<__LINE__<<("openDb error:%s",db.lastError())<<fileInfo.baseName();
                return;
            }
        }
        else
            return;

        QSqlQuery query(db);

        qDebug()<<"ClientThread:"<<db.lastError()<<"filename:"<<m_data.getDBFileName();

        //            QMap<QString,QString>mapvalue;
        if(query.exec(QString("select * from %1").arg(m_data.currentTable())))
        {
            while (query.next()){
                QString boxnum = query.value("boxnum").toString();
                QString boxvalue = query.value("boxvalue").toString();
                m_mapvalue.insert(boxnum,boxvalue);
                strlist_boxnum.append(boxnum);
                qDebug()<<"thread to weith and get the reale weith value:"<<boxnum<<boxvalue;
            }
        }

        struct send_head buf;
        memset(&buf,0,sizeof(buf));
        buf.head=0xbb;
        buf.cmd=0xff;
        QHashIterator<QString,QString> itor(m_mapvalue);
        while(itor.hasNext()){
            itor.next();
            QString value = itor.value();
            int index = value.indexOf(".");
            if(index!=-1){//19.1//index.2-4
                //                        int lengh = value.length();
                //有小数点
                int rihtlenth = value.length()-index-1;
                value = value.replace(".","");//去掉小数点
                if(rihtlenth==1)
                    value.append("0");
            }else{
                value.append("00");
            }
            //                    double qvalue = itor.value().toDouble();
            //                    quint32 intvalue = qvalue*100;
            quint32 intvalue = value.toULongLong();

            buf.data[itor.key().toInt()-1] = intvalue;
        }
        buf.fcc=GetCheckSum(&buf,sizeof(buf)-sizeof(quint32));

        if(socket->write(QByteArray::fromRawData((char *)&buf,sizeof(buf))) != -1){
            emit sig_UpdateState(m_data,BatchFeed::ClientConType_StartedWeigh,"");//称量完成，返回相应类型
//            static int countcmd = 5;
//            while(countcmd)
//            {
//                countcmd--;
//                if(socket->waitForReadyRead(600000)){//确认数据
//                    _byte_GetWeighValue = socket->readAll();
//                    if(checkData(_byte_GetWeighValue,0xff))//0xf9
//                    {
////                        emit sig_UpdateState(m_data,BatchFeed::ClientConType_WeighError,QStringLiteral("网络连接异常"));
//                        break;
//                    }
//                }
//            }
//            if(socket->waitForReadyRead(600000)){//确认数据
//                byte_weighValue = socket->readAll();
//                if(!checkData(byte_weighValue,0xf9)){
//                    if(!checkData(byte_weighValue,0xff)){
//                        //get real value.;
//                        byte_weighValue = QByteArray();
//                    }
//                }else{
//                    byte_weighValue = QByteArray();
//                }
//            }
//            if(socket->waitForReadyRead(600000)){
//                 if(!checkData(_byte_GetWeighValue,0xf9))
//                 {
//                    emit sig_UpdateState(m_data,BatchFeed::ClientConType_WeighError,QStringLiteral("网络连接异常"));
//                    return;
//                 }
//            }
        }else
            emit sig_UpdateState(m_data,BatchFeed::ClientConType_WeighError,socket->errorString());

        //称料完成
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_FinishedWeigh,"");
    }

    if(socket->waitForReadyRead(600000))
//    if(!_byte_GetWeighValue.isEmpty())
//    if(byte_weighValue.isNull()){
//        socket->waitForReadyRead(600000);
//        byte_weighValue = socket->readAll();;
//    }
//    if(!byte_weighValue.isNull())
    {
        //称量完成，返回实际称量值
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_ReadyReadWeighValue,"");
        QByteArray recv_bufbyte=socket->readAll();
        //        QByteArray recv_bufbyte(_byte_GetWeighValue);
        if(recv_bufbyte.isEmpty())
            qDebug()<<QStringLiteral("接收到的数据")<<recv_bufbyte.toHex();

        struct send_head *recv;
        recv=(struct send_head *)recv_bufbyte.data()+recv_bufbyte.indexOf(0xbb);

        for(int i = 0;i<24;i++){
            QString insertValue;
            if(recv->data[i] == 0xffffffff)////TODO:机子离线
                insertValue = "0";
            else
                insertValue = QString::number(recv->data[i]*0.01);
            m_mapPutvalue.insert(QString::number(i+1),insertValue);
            m_data.setCurrentPutData(m_mapPutvalue);
        }
    }
    else{
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_WeighError,socket->errorString());
        socket->disconnectFromHost();
        socket->deleteLater();
        return;
    }

    //! [1]-put.
    if(!m_data.IsIgnorError()){
        qDebug()<<" emit a signal.cause ignorError.";
        emit sig_finishedPutWeigh(m_data.currentTable() ,m_data.getCurrentPutData());

        //data record.
        jsonHelp jshlp;
        jshlp.insertEach(m_data.currentTable(),strlist_boxnum,m_mapPutvalue,m_data.getCurrentPutData());
        jshlp.insertGroup(QStringLiteral("组号:") + m_data.getGroupNum(),m_data.getIpadd());

        //                break;
        socket->disconnectFromHost();
        socket->deleteLater();
        return;
    }
    else{
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_PutConnected,"");
        struct send_head buf;
        memset(&buf,0,sizeof(buf));
        buf.head=0xbb;
        buf.cmd=0x0f;
        for(int i=0;i<24;i++){
            buf.data[i] = 0xffffffff;
        }
        buf.fcc=GetCheckSum(&buf,sizeof(buf)-sizeof(quint32));
        if(socket->write(QByteArray::fromRawData((char *)&buf,sizeof(buf))))
        {
            emit sig_UpdateState(m_data,BatchFeed::ClientConType_StartPut,"");
        }
        else
            emit sig_UpdateState(m_data,BatchFeed::ClientConType_PutError,socket->errorString());

        if(!socket->waitForReadyRead(600000)){
            //投料失败，返回失败原因
            emit sig_UpdateState(m_data,BatchFeed::ClientConType_PutError,socket->errorString());
            socket->disconnectFromHost();
            socket->deleteLater();
            return;
        }

        QByteArray recv_bufbyte=socket->readAll();
        struct send_head *recv;
        recv=(struct send_head *)recv_bufbyte.data()+recv_bufbyte.indexOf(0xbb);

        socket->disconnectFromHost();
        socket->deleteLater();

        if(!recv->cmd == 0xf4)
        {
            //投放出错，返回错误信息;
            emit sig_UpdateState(m_data,BatchFeed::ClientConType_PutError,socket->errorString());
            return;
        }

//#ifndef QT_DEBUG
        for(int i = 0;i<24;i++){
            if(recv->data[i] == 0xffffffff){//放料不成功
                QMap<QString,QString>::const_iterator itor = m_mapPutvalue.constFind(QString::number(i+1));
                if(itor != m_mapPutvalue.constEnd()){
                    m_mapPutvalue.insert(QString::number(i+1),"0");
                }
            }
        }
//#endif

        emit sig_finishedPutWeigh(m_data.currentTable(),m_data.getCurrentPutData());
        //投料完成-进行数据写入操作/保存到Excel、保存至本地记录
        emit sig_UpdateState(m_data,BatchFeed::ClientConType_FinishedPut,"");

        //write data back to excel.
        //写入excel
//        QString m_filename("E:/MyDocument/AppData/Local/YanboOrg/FishSoftware/data/1-GC14A1110.xlsm");
        QFileInfo fileInfo(m_data.getEXLFileName());
        QString dbName = "wr_"+fileInfo.baseName();
        {


        QSqlDatabase db = QSqlDatabase::addDatabase("QODBC",dbName);
//        dbName = QSqlDatabase::database().connectionName();

        QString dbn = QString("Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};"
                              "FIL={Excel xlsx};HDR=Yes;IMEX=1;Readonly=%1;DriverId=790;Dbq=%2;"
                              "DefaultDir=e:\\");
        dbn = dbn.arg(QString::number(0),m_data.getEXLFileName());
        db.setDatabaseName(dbn);
        if(!db.open()){
            qDebug()<<__LINE__<<("openDb error:%s",db.lastError())<<fileInfo.baseName();
        }
        QSqlQueryModel querymodel;
        QSqlQuery query(db);
        QString tablename = QStringLiteral("投饵机记录");
        query.exec(QString("select * from [%1$]").arg(tablename));
        querymodel.setQuery(query);
        int writecolumn = 4;
        int startcolumn = 0;
        QString writeFieldName("1");//默认列-标题为“1”所在列
        QString writeDateTimeFieldName;
//        QVariant boxFieldFirstValue;//data row's column value
        QString BoxFieldName = QStringLiteral("箱号");
        QString DateFieldName = QStringLiteral("序号");
        //get field name
        for(int k = 0;k<querymodel.columnCount();k++){
            if(querymodel.record().fieldName(k).contains(QStringLiteral("序号"))){
                startcolumn = k+1;
                writeDateTimeFieldName = querymodel.record(0).value(k).toString();
                DateFieldName = querymodel.record().fieldName(k);
                break;
            }
        }
        for(int i = startcolumn;i<querymodel.columnCount();i++){//找出所在列
            bool isfind = true;
            for(int j = 0;j<24;j++){//匹配所在列是否有数值记录
                if(querymodel.record(j).value(i).toDouble())
                {
                    isfind = false;
                    break;
                }
            }
//            if(querymodel.record(1).value(i).toDouble() == 0 && querymodel.record(24).value(i).toDouble() == 0){
            if(isfind){
                writecolumn = i;
                writeFieldName = querymodel.record().fieldName(i);
//                boxFieldFirstValue = querymodel.record(0).value(i-2);
//            qDebug()<<"valueRow1"<<querymodel.record(1).value(i)<<"BoxFieldName:"<<BoxFieldName<<"BoxFieldNameValue:"<<querymodel.record(0).value(i-2)<<querymodel.record(1).value(i-2)<<"writeFieldName:"<<writeFieldName<<querymodel.record().value(i)<<"writecolumn:"<<writecolumn<<"column:"<</*j*/0<<"row:"<<i;
                break;
            }
        }

        QSqlQuery queryinsert(db);
        ///insert value to excel.
        //insert the date to row 1
        QString str_value("0");
//        str_value = "'" + QDateTime::currentDateTime().toString("MM-dd-hh:mm:ss") + "'";
        str_value = QDateTime::currentDateTime().toString("MMdd.hhmmss");
//        if(!queryinsert.exec(QString("insert into [%1$] (%2) values (%3) where %4=%5").arg(tablename,writeFieldName,str_value,DateFieldName,writeDateTimeFieldName))){
//            queryinsert.exec(QString("update [%1$] set %2=%3 where %4=\"%5\"").
//                             arg(tablename,writeFieldName,str_value,DateFieldName,writeDateTimeFieldName));QStringLiteral("\"序号\"")
        if(!queryinsert.exec(QString("insert into [%1$] (%2) values (%3) where %4=%5").
                             arg(tablename,writeFieldName,QString("%1").arg(str_value),QString("%1").arg(DateFieldName),QStringLiteral("\"时间\"")))){
            queryinsert.exec(QString("update [%1$] set %2=%3 where %4=%5").
                             arg(tablename,writeFieldName,QString("%1").arg(str_value),QString("%1").arg(DateFieldName),QStringLiteral("\"时间\"")));

            qDebug()<<QStringLiteral("插入日期update:")<<queryinsert.lastError()<<queryinsert.lastQuery()
                   <<endl<<DateFieldName<<writeDateTimeFieldName;
        }

        //end.
        for(int m_insert = 1;m_insert<25;m_insert++){
            QString value;
            QMap<QString,QString>::const_iterator itor = m_mapPutvalue.constFind(QString::number(m_insert));
            if(itor != m_mapPutvalue.constEnd()){
                value = itor.value();
            }

            if(!queryinsert.exec(QString("insert into [%1$] (%2) values (%3) where %4=%5").
                                 arg(tablename,writeFieldName,(value),BoxFieldName,QString::number(m_insert))))
                queryinsert.exec(QString("update [%1$] set %2=%3 where %4=%5").
                                 arg(tablename,writeFieldName,(value),BoxFieldName,QString::number(m_insert)));
            qDebug()<<QStringLiteral("EachValue:")<<queryinsert.lastError()<<queryinsert.lastQuery();
        }
        db.commit();
        query.clear();
        queryinsert.clear();
        db.close();
//        QSqlDatabase::removeDatabase(dbName);
        qDebug()<<"defaultDBName:"<<QSqlDatabase::database().connectionName();
        QSqlDatabase::removeDatabase("qt_sql_default_connection");//不推荐。
        }//超出作用域，隐含对象QSqlDatabase::database()被删除。
//        QSqlDatabase::removeDatabase(dbName);

        //写入json文件
        jsonHelp jshlp;
        jshlp.insertEach(m_data.currentTable(),strlist_boxnum,m_mapPutvalue,m_data.getCurrentPutData());//! [1]
        jshlp.insertGroup(QStringLiteral("组号:") + m_data.getGroupNum(),m_data.getIpadd());//! [2]
    }
}


void ClientThread::setDefaultValue(int groupid, QString groupip)
{
    m_groupid = groupid;
    m_groupip = groupip;
}

void ClientThread::setData(GroupItemData data/*,QString currentItem*/)
{
    m_data = data;
    //    m_data.setCurrentTb(currentItem);
    m_groupid = m_data.getGroupNum().toInt();
    m_groupip = m_data.getIpadd();
    m_dbFilename = m_data.getDBFileName();
}

void ClientThread::slt_connecttoServer()
{
    //    struct send_head buf;
    //    memset(&buf,0,sizeof(buf));
    //    buf.head=0xbb;
    //    buf.cmd=0x0f;
    //    for(int i=0;i<24;i++){
    //        buf.data[i] = 0xffffffff;
    //    }
    //    buf.fcc=GetCheckSum(&buf,sizeof(buf)-sizeof(quint32));
    //    if(socket)
    //        socket->write(QByteArray::fromRawData((char *)&buf,sizeof(buf)));
}

void ClientThread::slt_getDateFromServer()
{
    //    emit sig_finishedPutWeigh();
    //    if(socket){
    //        socket->disconnectFromHost();
    //        socket->deleteLater();
    //    }
}

quint16 ClientThread::GetCheckSum (void *data, quint16 len)
{
    quint32 cksum = 0;
    quint16 *p = (quint16*)data;
    while (len > 1)
    {
        cksum += *p++;
        len -=2;
    }
    if (0 != len)
    {
        cksum += *(quint8 *)p;
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >>16);
    return ~cksum;
}

bool ClientThread::checkData(QByteArray byte, quint32 checkvalue)
{
    QByteArray recv_bufbyte(byte);
    struct send_head *recv;
    recv=(struct send_head *)recv_bufbyte.data()+recv_bufbyte.indexOf(0xbb);

    bool datacheck = false;
    if(recv->cmd == checkvalue){
        datacheck = true;
    }
    return datacheck;
}
